package com.ruoyi.common.core.redis;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.fake.domain.SysFakeRedisCache;
import com.ruoyi.common.core.redis.fake.service.ISysFakeRedisCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author win43
 */
@Component
public class FakeRedisCache {

    @Autowired
    private ISysFakeRedisCacheService fakeRedisCacheService;

    /**
     * key value createTime timeout timeUnit timeoutTime
     * <p>
     * 缓存基本的对象，Integer、String、实体类等
     * <p>
     * key-value
     * <p>
     * 查找key，不存在插入，存在更新
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String key, final T value) {
        SysFakeRedisCache old = fakeRedisCacheService.selectCache(key);
        if (old != null) {
            old.setCacheValue(JSON.toJSONString(value));
            old.setCacheType(value.getClass().toString());

            fakeRedisCacheService.updateCache(old);
        } else {
            SysFakeRedisCache sysFakeRedisCache = new SysFakeRedisCache();
            sysFakeRedisCache.setCacheKey(key);
            sysFakeRedisCache.setCacheValue(JSON.toJSONString(value));
            fakeRedisCacheService.insertCache(sysFakeRedisCache);
        }
    }

    /**
     * 缓存基本的对象，Integer、String、实体类等
     * <p>
     * 查找key,不存在插入，存在更新
     *
     * @param key      缓存的键值
     * @param value    缓存的值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
        SysFakeRedisCache old = fakeRedisCacheService.selectCache(key);
        if (old != null) {
            old.setCacheValue(JSON.toJSONString(value));

            old.setTimeout(timeout);
            old.setTimeUnit(timeUnit.name());

            long millisSeconds = TimeUnit.valueOf(timeUnit.name()).toMillis(timeout);
            Date now = new Date();
            Date timeoutDateTime = new Date(now.getTime() + millisSeconds);
            old.setTimeoutTime(timeoutDateTime);

            fakeRedisCacheService.updateCache(old);
        } else {
            SysFakeRedisCache sysFakeRedisCache = new SysFakeRedisCache();
            sysFakeRedisCache.setCacheKey(key);
            sysFakeRedisCache.setCacheValue(JSON.toJSONString(value));

            sysFakeRedisCache.setTimeout(timeout);
            sysFakeRedisCache.setTimeUnit(timeUnit.name());

            long millisSeconds = TimeUnit.valueOf(timeUnit.name()).toMillis(timeout);
            Date now = new Date();
            Date timeoutDateTime = new Date(now.getTime() + millisSeconds);
            sysFakeRedisCache.setTimeoutTime(timeoutDateTime);

            fakeRedisCacheService.insertCache(sysFakeRedisCache);
        }
    }

    public boolean expire(final String key, final Integer timeout, final TimeUnit timeUnit) {

        SysFakeRedisCache old = fakeRedisCacheService.selectCache(key);
        if (old != null) {

            old.setTimeout(timeout);
            old.setTimeUnit(timeUnit.name());

            long millisSeconds = TimeUnit.valueOf(timeUnit.name()).toMillis(timeout);
            Date now = new Date();
            Date timeoutDateTime = new Date(now.getTime() + millisSeconds);
            old.setTimeoutTime(timeoutDateTime);

            return fakeRedisCacheService.updateCache(old) > 0;
        }
        return false;
    }

    /**
     * 获得缓存的基本对象。
     * <p>
     * 查找key,不存在返回null,存在判断过期时间如果已过期，则返回null,并删除，否则返回该数据
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> Object getCacheObject(final String key) {
        SysFakeRedisCache old = fakeRedisCacheService.selectCache(key);
        if (old != null) {
            if (old.getTimeoutTime() == null || old.getTimeoutTime().getTime() < System.currentTimeMillis()) {
                return JSON.parseObject(old.getCacheValue(), Object.class);
            } else {
                fakeRedisCacheService.deleteCacheByKey(key);
            }
        }
        return null;
    }

    public <T> LoginUser getCacheObjectLoginUser(final String key) {
        SysFakeRedisCache old = fakeRedisCacheService.selectCache(key);
        if (old != null) {
            if (old.getTimeoutTime() == null || old.getTimeoutTime().getTime() < System.currentTimeMillis()) {
                return JSON.parseObject(old.getCacheValue(), LoginUser.class);
            } else {
                fakeRedisCacheService.deleteCacheByKey(key);
            }
        }
        return null;
    }

    /**
     * 删除单个对象
     * <p>
     * 查找key并删除
     *
     * @param key
     */
    public boolean deleteObject(final String key) {
        fakeRedisCacheService.deleteCacheByKey(key);
        return true;
    }

    /**
     * 删除集合对象
     * <p>
     * 遍历集合并删除
     *
     * @param collection 多个对象
     * @return
     */
    public long deleteObject(final Collection collection) {
        fakeRedisCacheService.deleteCacheByKeys(collection);
        return 1L;
    }

    /**
     * 获得缓存的基本对象列表
     * <p>
     * 使用like查询
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection<String> keys(final String pattern) {
        return fakeRedisCacheService.keys(pattern);
    }

}
